package com.canyou.activiti.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.canyou.activiti.entity.ProcessInstanceAddDTO;
import com.canyou.activiti.entity.ProcessInstanceVO;
import com.canyou.activiti.service.ProcessInstanceService;
import com.canyou.enums.ErrorCodeEnum;
import com.canyou.exception.CysBusinessException;
import com.canyou.utils.StringUtils;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceBuilder;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.runtime.api.model.impl.APIProcessInstanceConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author canyou
 * @since 2021-03-02
 */
@Service
public class ProcessInstanceServiceImpl implements ProcessInstanceService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private RepositoryService repositoryService;

    @Override
    public IPage<ProcessInstanceVO> getPageList(IPage<ProcessInstanceVO> page, String instanceName, String processKey) {
        ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery()
                .orderByProcessDefinitionId().asc().orderByProcessInstanceId().asc();
        if (StringUtils.isNotBlank(instanceName)) {
            processInstanceQuery.processInstanceNameLikeIgnoreCase("%" + instanceName + "%");
        }
        if (StringUtils.isNotBlank(processKey)) {
            processInstanceQuery.processDefinitionKey("%" + processKey + "%");
        }
        // 查询records
        List<ProcessInstance> processInstanceList = processInstanceQuery.listPage((int) ((page.getCurrent() - 1) * page.getSize()), (int) page.getSize());
        List<ProcessInstanceVO> list = new ArrayList<>();
        if (processInstanceList != null && !processInstanceList.isEmpty()) {
            list = processInstanceList.parallelStream()
                    .map(pi -> new ProcessInstanceVO()
                            .setId(pi.getId())
                            .setName(pi.getName())
                            .setProcessDefinitionId(pi.getProcessDefinitionId())
                            .setProcessDefinitionKey(pi.getProcessDefinitionKey())
                            .setProcessDefinitionVersion(pi.getProcessDefinitionVersion())
                            .setStartTime(pi.getStartTime())
                            .setDescription(pi.getDescription())
                            .setSuspensionState(((ExecutionEntityImpl) pi).getSuspensionState())
                            .setDeploymentId(pi.getDeploymentId())
                            .setStatus(new APIProcessInstanceConverter().from(pi).getStatus().toString())
                            .setResourceName(repositoryService.createProcessDefinitionQuery()
                                    .processDefinitionId(pi.getProcessDefinitionId())
                                    .singleResult()
                                    .getResourceName()))
                    .collect(Collectors.toList());
        }
        page.setRecords(list);
        // 查询总条数
        page.setTotal(processInstanceQuery.count());
        return page;
    }

    @Override
    public void deleteProcessInstance(String processInstanceId, String deleteReason) {
        // 不删除级联的其他数据
        runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
    }

    @Override
    public void activeOrSuspendProcessInstance(String processInstanceId, Integer suspensionState) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        // 获取流程实例, 如果不存在则异常
        if (processInstance == null) {
            throw new CysBusinessException(ErrorCodeEnum.ILLEGAL, "流程实例不存在");
        }
        int orgSuspensionState = ((ExecutionEntityImpl) processInstance).getSuspensionState();
        // 如果要变成的状态与当前状态一致, 那么抛出异常
        if (suspensionState.equals(orgSuspensionState)) {
            throw new CysBusinessException(ErrorCodeEnum.ILLEGAL,
                    StringUtils.format("当前已经是{}状态", Integer.valueOf(1).equals(suspensionState) ? "激活" : "挂起"));
        }
        if (Integer.valueOf(1).equals(suspensionState)) {
            runtimeService.activateProcessInstanceById(processInstanceId);
        } else {
            runtimeService.suspendProcessInstanceById(processInstanceId);
        }
    }

    @Override
    public ProcessInstanceVO startProcessInstance(ProcessInstanceAddDTO processInstanceAddDTO) {
        ProcessInstanceBuilder builder = runtimeService.createProcessInstanceBuilder()
                .processDefinitionKey(processInstanceAddDTO.getDefinitionKey())
                .name(processInstanceAddDTO.getInstanceName());
        Map<String, Object> variables = processInstanceAddDTO.getVariables();
        if (variables != null && variables.size() > 0) {
            builder.variables(variables);
        }
        ProcessInstance pi = builder.start();
        return new ProcessInstanceVO()
                .setId(pi.getId())
                .setName(pi.getName())
                .setProcessDefinitionId(pi.getProcessDefinitionId())
                .setProcessDefinitionKey(pi.getProcessDefinitionKey())
                .setProcessDefinitionVersion(pi.getProcessDefinitionVersion())
                .setStartTime(pi.getStartTime())
                .setDescription(pi.getDescription())
                .setSuspensionState(((ExecutionEntityImpl) pi).getSuspensionState())
                .setDeploymentId(pi.getDeploymentId());
    }

}
